import {
    Component, Input, OnChanges, ViewChild, OnInit, EventEmitter, Output,
    SimpleChanges, NgZone, ChangeDetectionStrategy, ChangeDetectorRef, Injector
} from '@angular/core';
import { ContextMenuItem } from '@farris/ui-context-menu';
import { NotifyService } from '@farris/ui-notify';
import { RowNode, TreeTableComponent } from '@farris/ui-treetable';
import { RefreshFormService, FormBasicService } from '@farris/designer-services';
import { of } from 'rxjs';
import { IdeTreeComponent } from '../ide-tree/ide-tree.component';
import { ControlTreeNode } from './entity/tree-node';
import { MoveUpDownContextMenuManger } from './service/move-context-menu.service';
import { ControlTreeBuilderService } from './service/tree-builder.service';
import { CollapsedControlTreeBuilderService } from './service/collapsed-tree-builder.service';

/**
 * 已废弃
 */
@Component({
    selector: 'mobile-control-tree',
    templateUrl: './mobile-control-tree.component.html',
    styleUrls: ['./mobile-control-tree.component.css'],
    providers: [ControlTreeBuilderService, CollapsedControlTreeBuilderService],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class MobileControlTreeComponent implements OnInit, OnChanges {
    /** 表单元数据JSON */
    @Input() domJson: any;


    /** 变更选中节点 */
    @Output() changeControlTreeNode = new EventEmitter<any>();

    /** 右键菜单前事件的回调方法，用于收集控件的菜单配置 */
    @Input() beforeShowContextMenu: (rowNode: RowNode, parentRowNode?: RowNode) => { menus: ContextMenuItem[], show: boolean };

    /** ide-tree实例 */
    @ViewChild('ideTree') private ideTree: IdeTreeComponent;

    /** 树json数据 */
    treeNodes: ControlTreeNode[] = [];

    /** 当前选中节点 */
    currentSelectedNode: ControlTreeNode;

    /** 当前选中节点id */
    currentSelectedNodeId: string;

    /** 展示控件属性类型：expanded完整控件树/ collapsed合并收折的控件树 */
    showType = 'collapsed';

    /** 收折的树json数据 */
    collpasedTreeNodes: ControlTreeNode[] = [];

    /** 展开的树json数据 */
    ideTreeNodes: ControlTreeNode[] = [];

    constructor(
        private controlTreeService: ControlTreeBuilderService,
        private collapsedControlTreeService: CollapsedControlTreeBuilderService,
        private ngZone: NgZone,
        private notifyService: NotifyService,
        private refreshFormService: RefreshFormService,
        private cdr: ChangeDetectorRef) { }

    ngOnInit() {
        this.refreshControlTree();
    }

    ngOnChanges(changes: SimpleChanges) {
        if (this.ideTree.tb) {
            this.ideTree.tb.isExpanded = false;
        }

        // 变更DOM结构，触发控件树刷新
        if (changes.domJson) {
            this.refreshControlTree();
        }
    }


    /**
     * 刷新控件树
     */
    refreshControlTree(selectedNodeId?: string) {
        if (this.domJson) {
            // // 重新选中节点
            // this.currentSelectedNodeId = selectedNodeId || this.getSelectedNodeId();

            // this.triggerTreeFocus(this.currentSelectedNodeId);
            this.treeNodes = this.controlTreeService.mappingFormDataToTree(this.domJson);

            // 重新选中节点
            this.currentSelectedNodeId = selectedNodeId || this.getSelectedNodeId();

            this.triggerTreeFocus(this.currentSelectedNodeId);

            this.cdr.detectChanges();
        }
    }



    /**
     * 点击树节点
     * @param $event 树节点点击事件
     */
    onSelectNodeChange($event) {
        this.currentSelectedNode = $event.node;

        // 有强依赖关系的控件，需要传递依赖的控件节点。例如TabPage 依赖Tab
        if (this.currentSelectedNode.dependentParentControl) {
            this.changeControlTreeNode.next({
                treeNode: $event.node,
                dependentTreeNode: $event.node.parent
            });
        } else {
            this.changeControlTreeNode.next({
                treeNode: $event.node
            });
        }


    }

    /**
     * 由外部触发控件树节点的点击事件
     * @param elementId 节点id
     */
    triggerTreeFocus(elementId: string) {

        // 从代码编辑器切换到可视化设计器的场景里会重复触发一个节点的点击事件，为了显示控件边框和并更新属性面板，此处先取消选中，再选中一次
        if (elementId === this.currentSelectedNodeId) {
            this.ideTree.tt.unSelectNode(this.currentSelectedNodeId);

            this.ngZone.runOutsideAngular(() => {
                setTimeout(() => {
                    this.ideTree.tt.selectNode(this.currentSelectedNodeId);
                });
            });
        } else {
            this.currentSelectedNodeId = elementId;
        }

        this.cdr.detectChanges();
    }

    /**
     * 更新控件树节点的数据，常用于修改控件名称后同步控件树
     * @param nodeId 节点id
     * @param data 需要更新的数据
     */
    updateControlTreeNodeData(nodeId: string, data: { [key: string]: string }) {
        this.ideTree.tt.update(nodeId, data);
        // this.collapsedTree.tt.update(nodeId, data);

        this.cdr.detectChanges();
    }

    /**
     * 获取应该选中的节点id
     */
    private getSelectedNodeId() {
        if (this.currentSelectedNode) {
            return this.currentSelectedNode.id;
        }
        if (this.treeNodes.length) {
            return this.treeNodes[0].data.id;
        }
    }

    /**
     * 展示右键菜单前事件
     * @param e 菜单参数
     */
    onBeforeShowContextMenu = (e: { data: RowNode }) => {
        let config;
        const rowNode = e.data as RowNode;
        const treeNode = rowNode.node as ControlTreeNode;
        // 有强依赖关系的控件，需要传递依赖的控件节点。例如TabPage 依赖Tab
        if (treeNode.dependentParentControl) {
            config = this.beforeShowContextMenu(rowNode, rowNode.parentRowNode);
        } else {
            config = this.beforeShowContextMenu(rowNode);
        }


        config = this.addMoveUpAndDownMenu(rowNode, config);

        return of(config);
    }

    /**
     * 追加上移下移菜单
     * @param rowNode 右键点击的树表行
     * @param config 菜单配置
     * @returns 菜单配置
     */
    private addMoveUpAndDownMenu(rowNode: RowNode, config: { show: boolean, menus: ContextMenuItem[] }) {
        const moveUpDownMenuManager = new MoveUpDownContextMenuManger(this.notifyService, this.refreshFormService);
        moveUpDownMenuManager.plainCompleteControlTreeNodes = this.controlTreeService.plainControlTreeNodes;

        const moveUpDownMenu = moveUpDownMenuManager.setMoveMenuConfig(rowNode);

        let menus = config.menus as any[];
        if (moveUpDownMenu.length) {
            if (menus.length) {
                menus = menus.concat(['-']);
            }
            menus = menus.concat(moveUpDownMenu);

            config.menus = menus;
            config.show = true;
        }

        return config;
    }

    onNodeExpandedAll() {
        this.treeNodes = this.ideTreeNodes;
        this.refreshControlTree();
    }
    onNodeCollapsedAll() {
        this.treeNodes = this.collpasedTreeNodes;
        this.refreshControlTree();
    }
}
